import pandas as pd
from ZIndex.tool import Util as Util
import copy


# 读取csv文件
baoSign = pd.read_csv(r'.\result\BaoSign.csv', sep=',')
# baoSign = baoSign.sort_values(by='')
# baoSign 数据去重，因节假日获取为上一交易日
baoSign = baoSign.drop_duplicates()
# 数据去重，获取股票列表Series
stock_list = baoSign.drop_duplicates(['code'])
df_rowNum = stock_list.shape[0]
# 对数据进行切分，7：3， 70%的进行权重计算，余下的按权重来计算概率
# splitNum = 0.7
# trainNum = math.ceil(df_rowNum * splitNum)
# sign = baoSign.head([trainNum])
# signWeight = baoSign.tail([df_rowNum - trainNum])
sign = baoSign

stock_series = stock_list['code']
result = pd.DataFrame()
result['code'] = stock_list['code']

# 计算各指标准确率
def index_acc(index_name, acc_name, sign, value):
    """
    计算各指标准确率
    :param index_name:
    :param df:
    :return:
    """
    # 逐行处理sign
    # index_name = index_name + 'acc'

    # 获取sign中code与series中code相同的数据，形成新的dataframe
    temp_df = sign[sign['code'].isin([value])]
    # print(temp_df)
    temp_df_row = temp_df.shape[0]
    temp_row_num = 0
    for i in range(0, len(temp_df)):
        temp_row_num = temp_row_num + 1
        # 当前行与前一行数据进行比对，主要针对close价格进行对比，
        if temp_row_num < temp_df_row:  # 最后一行不判断了，默认置为0
            # 买入信号的情况下，通过判断close价格来对信号准确性进行判断
            if temp_df.iloc[i + 1][index_name] > 0:
                # 如果当前行的close价格高于前一日close价格
                if temp_df.iloc[i]['close'] > temp_df.iloc[i + 1]['close']:
                    temp_df.iloc[i + 1, temp_df.shape[1] - 1] = 1
            elif temp_df.iloc[i + 1][index_name] < 0:
                # 如果当前行的close价格低于前一日close价格
                if temp_df.iloc[i]['close'] < temp_df.iloc[i + 1]['close']:
                    temp_df.iloc[i + 1, temp_df.shape[1] - 1] = 1
    # print(temp_df)
    # 获取该组合下个股准确率，先求出准确率不等0的指标有多少个
    sign_num = temp_df[index_name].apply(lambda x: Util.sumSign_fun(x))
    acc_num = temp_df[acc_name].apply(lambda x: Util.sumSign_fun(x))
    # result.loc[value, 'acc'] = acc_num/sign_num
    if sign_num.sum() >0:
        result.loc[index, acc_name] = round(acc_num.sum() / sign_num.sum(), 2)
    else:
        result.loc[index, acc_name] = 0

    return result


# test_Index_List = ['KDJ_S','LWR_S','MACD_S','BRAR_S', 'LB_S','VRSI_S','MA_S','BOLL_S','OBV_S','MFI_S']
test_Index_List = ['KDJ_S','WR_S','MACD_S', 'LB_S', 'BOLL_S','OBV_S','MFI_S']


# 存储临时变量 准确率、指标组合、各股准确率
top_acc_index_list = []
tempTopAcc = 0
top_acc_index_df = pd.DataFrame()
# test_Index_List.append('sum')
# 从待选指标中不重复抽样5个指标
# 随机指标个数
select_num = 5
for i in range(Util.countMN(len(test_Index_List), select_num)):
    select_index = Util.listRandomChoice(test_Index_List, select_num)

    result_select_index = copy.deepcopy(select_index)
    result_select_index.insert(0, 'date')
    result_select_index.insert(1, 'code')
    result_select_index.insert(2, 'close')

    sign_result_df = sign.loc[:, result_select_index]
    sign_result_df['sum'] = sign_result_df[select_index].apply(lambda x: x.sum(), axis=1)
    tempSign = copy.deepcopy(sign_result_df)
    select_index.append('sum')

    finalResult = pd.DataFrame()
    print(select_index)

    acc_name_list = ['code']
    for column in select_index:
        # print(column)
        index_name = column
        acc_name = index_name + '_acc'
        acc_name_list.append(acc_name)
        for index, value in stock_series.items():
            tempSign[acc_name] = 0
            finalResult = index_acc(index_name, acc_name, tempSign, value)

    Util.dataFrameToCsv(finalResult.loc[:, acc_name_list], "/result/BaoSign_acc_all.csv", True, True)
    # print(finalResult['sum_acc'])
    print(finalResult['sum_acc'].sum())
    # 求平均准确率
    sum_acc = finalResult['sum_acc'].sum()
    average_acc = round(sum_acc / finalResult.shape[0], 2)

    if tempTopAcc < average_acc:
        tempTopAcc = average_acc
        top_acc_index_list = select_index
        top_acc_index_df = copy.deepcopy(finalResult.loc[:, acc_name_list])

    data = '--'.join(result_select_index)
    data = data + ", 平均准确率为：" + str(average_acc)
    Util.dataToTxt(data, '/result/BaoSign_acc.txt', True)


# 找到准确认最高的一组，
print("###准确率最高的组合是###")
print(top_acc_index_list)
print(tempTopAcc)
print(top_acc_index_df)


# 计算各指标权重
def computer_index_weight(top_acc_index_list, top_acc_index_df):
    weightResult = {}

    top_acc_index_list.remove('sum')
    # 通过指标的准确率来计算权重
    for i, index in enumerate(top_acc_index_list):
        # print("序号：%s   值：%s" % (i + 1, index))
        # 从Dataframe中取该列，求该列的平均准确率，存入至weightResult
        # tempSign[acc_name] = 0
        # weightResult = index_acc(index_name, acc_name, tempSign, value)
        # signAcc.index_acc(index, sign)

        colName = index + '_acc'
        sum_acc = top_acc_index_df[colName].sum()
        # 计算非零个数
        index_zero_num = len(top_acc_index_df[top_acc_index_df[colName] != 0])
        weightResult[index] = round(sum_acc / index_zero_num, 2)

    # 获取各指标的平均准确率
    print("###指标平均准确率###")
    print(weightResult)
    weight_all = sum(weightResult.values())
    for i, index in enumerate(top_acc_index_list):
        weightResult[index] = round(weightResult[index] /weight_all, 2 )
    print("###各指标权重###")
    print(weightResult)

computer_index_weight(top_acc_index_list, top_acc_index_df)


